package com.rj.core.algorithm;

import javax.crypto.Cipher;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 非对称加密算法枚举
 */
public enum RsaAgorithm {
    /**
     * RSA/ECB/PKCS1Padding
     */
    RSA_ECB_PKCS1PADDING("RSA/ECB/PKCS1Padding"),
    /**
     * RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING
     */
    RSA_ECB_OAEPWITHSHA_512ANDMGF1PADDING("RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING"),
    /**
     * RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING
     */
    RSA_ECB_OAEPWITHSHA_256ANDMGF1PADDING("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
    public String transformation;
    public String algorithm;

    RsaAgorithm(String transformation) {
        this.transformation = transformation;
        this.algorithm = name().split("_")[0];
    }

    public KeyPair generateRsaKeyPair(int keySize) throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);
        generator.initialize(keySize);
        return generator.generateKeyPair();
    }

    /**
     * 生成RSA密钥对 (2048位)
     */
    public KeyPair generateRsaKeyPair() throws Exception {
        return this.generateRsaKeyPair(2048);
    }
    /**
     * 加密或解密
     *
     * @param mode 加密或解密模式
     * @param data 数据
     * @param keyBytes 密钥
     * @return
     */
    public byte[] crypt(int mode, byte[] data, byte[] keyBytes) {
        boolean  isEncrypt = Cipher.ENCRYPT_MODE ==  mode;
        try {
            Key key;
            if(isEncrypt){
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
                KeyFactory kf = KeyFactory.getInstance(algorithm);
                key = kf.generatePublic(keySpec);
            }else{
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
                KeyFactory kf = KeyFactory.getInstance(algorithm);
                key = kf.generatePrivate(keySpec);
            }
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(mode, key);
            return cipher.doFinal(data);
        } catch (Exception e){
            throw new RuntimeException(isEncrypt?"RSA加密失败":"RSA解密失败",e);
        }
    }
}
